package m2acsis.algebre.anneau;

import java.math.BigDecimal;
import java.math.MathContext;

import m2acsis.algebre.ElemAnneau;
import m2acsis.algebre.ElemGroupe;

public class Complexe implements ElemAnneau {

	private BigDecimal a;
	private BigDecimal b;
	
	public Complexe(double a, double b) {
		this.a = new BigDecimal(String.valueOf(a));
		this.b = new BigDecimal(String.valueOf(b));
	}
	
	public double reel(){
		return a.doubleValue();
	}
	
	public double imaginaire(){
		return b.doubleValue();
	}
	
	public double module() {
		BigDecimal doublea = a.pow(2, MathContext.DECIMAL128);
		BigDecimal doubleb = b.pow(2,  MathContext.DECIMAL128);
		return Math.sqrt(doublea.add(doubleb).doubleValue());
    }
	
	public ElemAnneau conjugue(){
		return new Complexe(a.doubleValue(), -1 * b.doubleValue());
	}
	
	@Override
	public ElemAnneau inverse() {
		
		if(this.equals(neutre()))
			return null;
		
		BigDecimal doublea = a.pow(2, MathContext.DECIMAL128);
		BigDecimal doubleb = b.pow(2, MathContext.DECIMAL128);
		
		BigDecimal length = doublea.add(doubleb, MathContext.DECIMAL128);
		
		BigDecimal diva = a.divide(length, MathContext.DECIMAL128);
		BigDecimal divb = b.divide(length, MathContext.DECIMAL128);
	    return new Complexe(diva.doubleValue(), divb.negate().doubleValue());
	}

	@Override
	public ElemAnneau produit(ElemAnneau e) {
		
		if(e instanceof Complexe){
			
			Complexe c = (Complexe) e;
			
			//les flotantes peuvent conduire à une erreur
			if(c.equals(inverse()))
				return unite();
			
			BigDecimal ea = a.multiply(c.a,  MathContext.DECIMAL128);
			BigDecimal eb = b.multiply(c.b,  MathContext.DECIMAL128);
			
			BigDecimal ia = a.multiply(c.b,  MathContext.DECIMAL128);
			BigDecimal ib = b.multiply(c.a,  MathContext.DECIMAL128);
			
			return new Complexe(ea.subtract(eb).doubleValue(), ia.add(ib).doubleValue());
		}
		
		return null;
	}

	@Override
	public ElemAnneau unite() {
		return new Complexe(1, 0);
	}

	@Override
	public ElemGroupe neutre() {
		return new Complexe(0, 0);
	}

	@Override
	public ElemGroupe oppose() {
		return new Complexe(a.negate().doubleValue(), b.negate().doubleValue());
	}

	@Override
	public ElemGroupe somme(ElemGroupe e) {
		
		if(e instanceof Complexe){
			
			Complexe ce = (Complexe) e;
			return new Complexe(a.add(ce.a).doubleValue(), b.add(ce.b).doubleValue());
		}
		
		return null;
	}
	
	@Override
	public String toString() {
		
		String result = "<";
		
		if (a.compareTo(BigDecimal.ZERO) > 0)
			result += "+" + a;
		else if (a.compareTo(BigDecimal.ZERO) < 0)
			result += "-" + a.negate();
		else
			result += "+" + a;
		
		if ( b.compareTo(BigDecimal.ZERO) > 0)
            result += " +" + b + "i>";
		else if (b.compareTo(BigDecimal.ZERO) < 0) 
            result += " -" + b.negate()+ "i>";
		else
			result += " +" + b +"i>";
		
		if(result.equals("<"))
			return "Wrong complex number";
		
		
        return result;
	}

	public boolean equals(Object obj) {
	    try {
	      Complexe c = (Complexe)obj;
	      return c.a.equals(a) && c.b.equals(b);
	    }
	    catch (Exception e) {
	      return false;
	    }
	  }
}
